package cn.murky.admin.quartz.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.murky.admin.quartz.service.impl.AdminJobLogServiceImpl;
import cn.murky.common.exception.TaskException;
import cn.murky.quartz.constant.ScheduleConstants;
import cn.murky.quartz.domain.dto.SysJobPageDTO;
import cn.murky.quartz.domain.entity.SysJob;
import cn.murky.quartz.domain.entity.table.SysJobTableDef;
import cn.murky.quartz.utils.CronUtils;
import cn.murky.quartz.utils.ScheduleUtils;
import cn.murky.common.web.ApiResult;
import cn.murky.core.web.BaseController;
import cn.murky.quartz.service.ISysJobService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.If;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.noear.solon.annotation.*;
import org.noear.solon.validation.annotation.Valid;
import org.quartz.SchedulerException;

import static cn.murky.quartz.constant.ErrorConstants.KEY_ALREADY_EXISTS_ERROR;


/**
 * 调度任务信息操作处理
 *
 * @since hans
 */
@Controller
@Valid
@Mapping("monitor/job")
public class SysJobController extends BaseController<AdminJobLogServiceImpl> {

    /**
     * 查询定时任务列表
     */
    @SaCheckPermission(value = "monitor:job")
    @Mapping("/page")
    @Get
    public ApiResult<Page<SysJob>> list(SysJobPageDTO sysJobPageDTO) {
        SysJobTableDef SYS_JOB = SysJobTableDef.SYS_JOB;
        Page<SysJob> page = baseService.page(sysJobPageDTO, QueryWrapper.create()
                .where(SYS_JOB.JOB_NAME.like(sysJobPageDTO.getJobName(), If::hasText)
                        .and(SYS_JOB.JOB_GROUP.eq(sysJobPageDTO.getJobGroup(), If::notNull)
                        .and(SYS_JOB.STATUS.eq(sysJobPageDTO.getStatus(), If::notNull)
                        .and(SYS_JOB.INVOKE_TARGET.like(sysJobPageDTO.getInvokeTarget(), If::hasText)))
                )));
        return ApiResult.ok(page);
    }


    /**
     * 获取定时任务详细信息
     */
    @SaCheckPermission("monitor:job")
    @Mapping("/{jobId}")
    @Get
    public ApiResult<SysJob> getInfo(Long jobId) {
        return ApiResult.ok(baseService.getById(jobId));
    }

    /**
     * 新增定时任务
     */
    @SaCheckPermission("monitor:job:add")
    @Post
    @Mapping
    public ApiResult<?> add(@Body SysJob job) throws SchedulerException, TaskException {
        if (!CronUtils.isValid(job.getCronExpression())) {
            return ApiResult.fail("system.quartz.add.cronError",job.getJobName());
        } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), ScheduleConstants.LOOKUP_RMI)) {
            return ApiResult.fail("system.quartz.add.rmiError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{ScheduleConstants.LOOKUP_LDAP, ScheduleConstants.LOOKUP_LDAPS})) {
            return ApiResult.fail("system.quartz.add.ldapError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{ScheduleConstants.HTTP, ScheduleConstants.HTTPS})) {
            return ApiResult.fail("system.quartz.add.httpError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), ScheduleConstants.JOB_ERROR_STR)) {
            return ApiResult.fail("system.quartz.add.invokeError",job.getJobName());
        } else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) {
            return ApiResult.fail("system.quartz.add.whilteError",job.getJobName());
        }
        return toResult(baseService.insertJob(job));
    }

    /**
     * 修改定时任务
     */
    @SaCheckPermission("monitor:job:edit")
    @Put
    @Mapping
    public ApiResult<?> edit(@Body SysJob job) throws SchedulerException, TaskException {
        if (!CronUtils.isValid(job.getCronExpression())) {
            return ApiResult.fail("system.quartz.edit.cronError",job.getJobName());
        } else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), ScheduleConstants.LOOKUP_RMI)) {
            return ApiResult.fail("system.quartz.edit.rmiError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{ScheduleConstants.LOOKUP_LDAP, ScheduleConstants.LOOKUP_LDAPS})) {
            return ApiResult.fail("system.quartz.edit.ldapError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{ScheduleConstants.HTTP, ScheduleConstants.HTTPS})) {
            return ApiResult.fail("system.quartz.edit.httpError",job.getJobName());
        } else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), ScheduleConstants.JOB_ERROR_STR)) {
            return ApiResult.fail("system.quartz.edit.invokeError",job.getJobName());
        } else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) {
            return ApiResult.fail("system.quartz.edit.whilteError",job.getJobName());
        }
        return toResult(baseService.updateJob(job));
    }

    /**
     * 定时任务状态修改
     */
    @SaCheckPermission("monitor:job:changeStatus")
    @Mapping("/changeStatus")
    @Put
    public ApiResult<?> changeStatus(@Body SysJob job) throws SchedulerException {
        SysJob newJob = baseService.getById(job.getId());
        newJob.setStatus(job.getStatus());
        return toResult(baseService.changeStatus(newJob));
    }

    /**
     * 定时任务立即执行一次
     */
    @SaCheckPermission("monitor:job:changeStatus")
    @Mapping("/run")
    @Post
    public ApiResult<?> run(@Body SysJob job) throws SchedulerException {
        return toResult(baseService.run(job),KEY_ALREADY_EXISTS_ERROR);
    }

    /**
     * 删除定时任务
     */
    @SaCheckPermission("monitor:job:remove")
    @Mapping("/{jobIds}")
    @Delete
    public ApiResult<?> remove(Long[] jobIds) throws SchedulerException, TaskException {
        baseService.deleteJobByIds(jobIds);
        return ApiResult.ok();
    }
}
